#include "tword.h"

#define MULTIPLICATION_W 16

/*
	@number : word total number
	return value : r (2^r ~ number)
*/
static int 
closest_r(int number)
{
	int i, r = 0;
	
	for (i = 31; i >=0; --i) {
		if (number & (1 << i)) {
			if (r == 0) {
				r = i;
			} else {
				return r + 1;
			}
		}
	}
	
	return r;
}


#ifdef _WIN32
static long int
get_random_number()
{
	static int seed;
	long int rdm;
	SYSTEMTIME time;


	GetSystemTime(&time);
	seed += time.wMilliseconds + time.wSecond;

	srand(seed);
	rdm = rand();

	return rdm;
}
#else
static long int
get_random_number()
{
	unsigned int seed;
	struct timeval tv;
	long int rdm;

	gettimeofday (&tv, NULL);
	seed = tv.tv_sec + tv.tv_usec;
	srand(seed);	
	rdm = random();
	
	return rdm;
}
#endif

/*
	w = 16 (16bit)
	a = (2^16 ~ 2^15)
	k = Random number (generated by random function)
	r = (dynamic check the word volume to determine the closest r)
	H(k) = (a.k mod 2^w) rsh (w -r)
	
*/
static int 
h(unsigned int a, unsigned int k, 
		unsigned int w, unsigned int r){
	int slot;
	
	slot = ((a * k) % (1 << w)) >> (w - r);	
	
	DBG_PRINT("((%u*%u)%(1<<%u)>>%u  ", a, k, w, w-r);
	
	DBG_PRINT("slot=%d\n", slot);

	return slot;
}

static int 
get_random_slot()
{
	long int k;
	int r;
	int slot;
	
	word_t *start = WORD_HEAD;
	int counter = GET_WORD_CTR();

	k = get_random_number();
	r = closest_r(counter);

	slot = h((1 << (MULTIPLICATION_W - 1))+10000, (unsigned int)k, 
		  MULTIPLICATION_W, r);
	if (slot >= counter)
		slot = slot % counter;

	DBG_PRINT("hello [%d] world! [r=%d] [slot=%d]\n", 
		counter, r, slot);

	return slot;
}

static void 
print_word(int slot)
{
	static int index = 0;
	word_t *start = WORD_HEAD;
	int counter = GET_WORD_CTR();
	int i;

	if (slot > counter)
		return;
	
	for(i = 0; i != slot; i++) {
		start = start->next;
	}
	fprintf(stderr, "%2d) %-60s\n", ++index, start->name); 
}

void
do_random_test(WORD_LANG from, WORD_LANG to, int number)
{

	int i, slot, cmd;

BEGIN:
	for (i = 0; i < number; i++) {
		slot = get_random_slot();
		print_word(slot);
	}
	fprintf(stderr, "(n)->next, (q)->quit\n");
INPUT:
#ifdef _WIN32
	cmd = getch(stdin);
#else
	cmd = getchar();
#endif
	switch (cmd) {
	case 'n':
#ifndef _WIN32
		fprintf(stderr, "%c[%dA", 0x1b, number + 1);
#endif
		goto BEGIN;
	case 'q':
		break;
	default:
		goto INPUT;
	}

	return;
}

